---
type: tutorial
title: Construa seu primeiro layout
description: |-
  Tutorial: Construa seu primeiro blog Astro —
  Refatore elementos comuns em um layout de página reutilizável
i18nReady: true
---
import Box from '~/components/tutorial/Box.astro';
import Checklist from '~/components/Checklist.astro';
import MultipleChoice from '~/components/tutorial/MultipleChoice.astro';
import Option from '~/components/tutorial/Option.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import { Steps } from '@astrojs/starlight/components';


<PreCheck>
  - Refatorar elementos comuns em um layout de página
  - Utilizar um elemento `<slot />` do Astro para colocar conteúdos da página em um layout
  - Passar valores específicos da página como props para seu layout
</PreCheck>

Você ainda tem alguns componentes Astro repetidamente renderizados em cada página. É hora de refatorar novamente para criar um layout de página compartilhado!

## Crie seu primeiro componente de layout

<Steps>
1. Crie um novo arquivo em `src/layouts/BaseLayout.astro`. (Você precisará criar uma nova pasta `layouts` primeiro.)

2. Copie **todo o conteúdo** de `index.astro` para seu novo arquivo, `BaseLayout.astro`.

    ```astro title="src/layouts/BaseLayout.astro"
    ---
    import Header from '../components/Header.astro';
    import Footer from '../components/Footer.astro';
    import '../styles/global.css';
    const pageTitle = "Página Inicial";
    ---
    <html lang="pt-BR">
      <head>
        <meta charset="utf-8" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <meta name="viewport" content="width=device-width" />
        <meta name="generator" content={Astro.generator} />
        <title>{pageTitle}</title>
      </head>
      <body>
        <Header />
        <h1>{pageTitle}</h1>
        <Footer />
        <script>
          import "../scripts/menu.js";
        </script>
      </body>
    </html>
    ```
  </Steps>

## Utilize seu layout em uma página

<Steps>
3. Substitua o código em `src/pages/index.astro` com o seguinte:

    ```astro title="src/pages/index.astro"
    ---
    import BaseLayout from '../layouts/BaseLayout.astro';
    const pageTitle = "Página Inicial";
    ---
    <BaseLayout>
      <h2>O subtítulo incrível do meu blog</h2>
    </BaseLayout>
    ```
 
4. Verifique a pré-visualização do navegador novamente para observar o que (ou, alerta de spoiler: _não_!) mudou.
    
5. Adicione um elemento `<slot />` ao `src/layouts/BaseLayout.astro` acima do componente de rodapé, e então verifique a pré-visualização do navegador de sua página de Início e observe o que de fato _realmente_ mudou desta vez!

    ```astro title="src/layouts/BaseLayout.astro" ins={18}
    ---
    import Header from '../components/Header.astro';
    import Footer from '../components/Footer.astro';
    import '../styles/global.css';
    const pageTitle = "Página Inicial";
    ---
    <html lang="pt-BR">
      <head>
        <meta charset="utf-8" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <meta name="viewport" content="width=device-width" />
        <meta name="generator" content={Astro.generator} />
        <title>{pageTitle}</title>
      </head>
      <body>
        <Header />
        <h1>{pageTitle}</h1>
        <slot />
        <Footer />
        <script>
          import "../scripts/menu.js";
        </script>
      </body>
    </html>
    ```
  </Steps>

 O `<slot />` permite que você injete (ou "encaixe") **conteúdo filho** escrito entre as tags de abertura e fechamento `<Componente></Componente>` em qualquer arquivo `Componente.astro`.

## Passe valores específicos da página como props

<Steps>
6. Passe o título da página para seu componente de layout de `index.astro` utilizando um atributo do componente:

    ```astro title="src/pages/index.astro" 'pageTitle={pageTitle}'
    ---
    import BaseLayout from '../layouts/BaseLayout.astro';
    const pageTitle = "Página Inicial";
    ---
    <BaseLayout pageTitle={pageTitle}>
      <h2>O subtítulo incrível do meu blog</h2>
    </BaseLayout>
    ```

7. Modifique o script do seu componente de layout `BaseLayout.astro` para receber um título da página através de `Astro.props` em vez de definí-lo como uma constante.

    ```astro title="src/layouts/BaseLayout.astro" del={5} ins={6}
    ---
    import Header from '../components/Header.astro';
    import Footer from '../components/Footer.astro';
    import '../styles/global.css';
    const pageTitle = "Página Inicial";
    const { pageTitle } = Astro.props;
    ---
    ```

8. Confira a pré-visualização no navegador para verificar que o título da página não mudou. Ele tem o mesmo valor, mas agora está sendo apresentado dinamicamente. E agora, cada página individual poderá especificar seu próprio título para o layout.
</Steps>

<Box icon="puzzle-piece">

## Tente você mesmo - Utilize seu layout em todo lugar

**Refatore** suas outras páginas (`blog.astro` e `about.astro`) para que elas utilizem seu novo componente `<BaseLayout>` para mostrar elementos comuns da página.

Não se esqueça de:

- Passar o título da página como props via atributo do componente.

- Deixar o layout como responsável pela apresentação HTML de quaisquer elementos comuns.

- Mover quaisquer tags `<style>` do `<head>` da página com estilos que você quer manter para o modelo de página HTML.

- Excluir qualquer coisa de cada página individual que agora é manipulada pelo layout, incluindo:

  - Elementos HTML
  - Componentes e suas importações
  - Regras CSS em uma tag `<style>` (como `<h1>` na sua página Sobre)
  - Tags `<script>`

:::note[Mantendo os estilos da sua página Sobre]
Usar o `<BaseLayout>` para mostrar sua página `about.astro` significa que você perderá a tag `<style>` adicionada ao `<head>` dessa página. Para continuar a estilizar itens somente no nível da página usando o estilo escopado do Astro, mova a tag `<style>` para o corpo do componente de página. Isso permite que você estilize **elementos criados neste componente de página** (como uma lista de suas habilidades).
  
Como agora seu `<h1>` é criado pelo seu componente de layout, você pode adicionar o atributo `is:global` em sua tag de estilo para afetar todos os elementos dessa página, incluindo aqueles criados por outros componentes: `<style is:global define:vars={{ skillColor, fontWeight, textCase }}>`
:::
</Box>



<Box icon="question-mark">

### Teste seu conhecimento

1. Um componente Astro (arquivo `.astro`) pode funcionar como:

    <MultipleChoice>
      <Option>página</Option>
      <Option>componente de UI</Option>
      <Option>layout</Option>
      <Option isCorrect>todas as alternativas acima, pois componentes Astro são muito funcionais! 🏗️</Option>
    </MultipleChoice>

2. Para mostrar o título de uma página na página, você pode:

    <MultipleChoice>
      <Option>
        usar um elemento HTML padrão na página com texto estático (como `<h1>Página Inicial</h1>`)
      </Option>
      <Option>
        usar um elemento HTML padrão na página referenciando uma variável definida no script frontmatter do seu componente (como `<h1>{tituloPagina}</h1>`)
      </Option>
      <Option>
        usar um componente de layout na página, passando o título como atributo do componente (como `<BaseLayout titulo="Página Inicial" />` ou `<BaseLayout titulo={tituloPagina} />`)
      </Option>
      <Option isCorrect>
        todas as alternativas acima, pois Astro permite que você use HTML simples ou turbine-o com alguns scripts e componentes! 💪
      </Option>
    </MultipleChoice>

3. Informação pode ser passada de um componente para outro ao:

    <MultipleChoice>
      <Option>
        importar um componente de UI e mostrá-lo no modelo de outro componente
      </Option>
      <Option>
        passar props para um componente onde ele é renderizado através de um atributo do componente
      </Option>
      <Option>
        enviar conteúdo HTML para ser mostrado dentro de outro componente utilizando um `<slot />` de placeholder
      </Option>
      <Option isCorrect>
        todas as alternativas acima, pois Astro foi construido para aproveitar o design baseado em componentes! 🧩
      </Option>
    </MultipleChoice>

</Box>

<Box icon="check-list">

## Checklist

<Checklist>
- [ ] Eu posso criar um componente de layout Astro com um `<slot />`.
- [ ] Eu posso enviar propriedades específicas da página para um layout.
</Checklist>
</Box>

### Recursos

- [Componentes de layout Astro](/pt-br/basics/layouts/)

- [`<slot />` do Astro](/pt-br/basics/astro-components/#slots)
